Skip to content

feat(logs): add Troubleshoot in Chat button for errored runs#5341

Merged
waleedlatif1 merged 8 commits into
stagingfrom
worktree-logs-troubleshoot-in-chat
Jul 2, 2026
Merged

feat(logs): add Troubleshoot in Chat button for errored runs#5341
waleedlatif1 merged 8 commits into
stagingfrom
worktree-logs-troubleshoot-in-chat

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

  • Adds a Troubleshoot in Chat button to the log details panel for errored runs (failed status, has an executionId, not a Chat/mothership run).
  • Clicking it tags the failed run as a logs context (executionId) and auto-sends a message to Chat asking Sim to investigate and fix the error — the server resolves the tagged run into the agent's context, so it sees the full error.
  • Ports the old copilot "Fix in Chat" behavior to mothership and adds the run-ID tagging that never got carried over.
  • Cross-route handoff rides a one-shot MothershipHandoffStorage (localStorage) consumed exactly once on the home-surface mount, so the tagged run + prompt survive the Logs → Chat navigation. Consume clears atomically (fires once, even under StrictMode / reload).

Type of Change

  • New feature

Testing

  • Unit tests for MothershipHandoffStorage (round-trip + trim, one-shot consume, empty-message guard, max-age expiry clears).
  • type-check, biome, check:client-boundary, and check:api-validation all pass.
  • Verified the end-to-end path: button → handoff stored → /home mount consumes → sendMessage(msg, undefined, contexts) → POST /api/mothership/chat with createNewChat: true and the raw contexts (envelope + context schema are .passthrough(), so executionId survives) → processExecutionLogFromDb(executionId) injects the run error into the agent.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

Errored log runs now surface a "Troubleshoot in Chat" action in the log
details panel. It tags the failed run as a logs context (executionId) and
auto-sends a message to Chat asking Sim to investigate and fix the error,
porting the old copilot "Fix in Chat" behavior to mothership and adding
run-ID tagging.

Cross-route handoff rides a one-shot MothershipHandoffStorage consumed once
on the home surface mount, so the tagged run + prompt survive the navigation
from Logs to Chat and the agent receives the full run error via the resolved
logs context.
@vercel

vercel Bot commented Jul 1, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Jul 2, 2026 12:13am

Request Review

@cursor

cursor Bot commented Jul 1, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
New cross-route chat handoff and mothership event contract changes could affect existing “Fix in Chat” flows if consumption/preventDefault behavior regresses; scope is client-only with tests on the storage path.

Overview
Adds Troubleshoot in Chat on failed workflow runs in log details (requires executionId, excludes mothership-triggered runs). The action sends a prefilled prompt with a logs ChatContext tagging the run so Chat can investigate the failure.

Cross-surface delivery: sendMothershipMessage now accepts optional contexts, dispatches a cancelable event, and returns whether a mounted chat consumed it (preventDefault). Workspace home forwards contexts into sendMessage and, on the new-chat surface only, consumes a one-shot MothershipHandoffStorage handoff when no listener is mounted—otherwise log details stores the handoff and navigates to /home only after a successful write.

Includes unit tests for handoff store/consume (trim, one-shot, expiry, corruption). Log details overview rows get minor UI tweaks (Badge/Chip, less row hover).

Reviewed by Cursor Bugbot for commit 462f4cd. Configure here.

Comment thread apps/sim/app/workspace/[workspaceId]/home/home.tsx Outdated
@greptile-apps

greptile-apps Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds a Troubleshoot in Chat button to the log details panel that activates for failed, non-mothership runs. It uses a two-path delivery: a cancelable custom DOM event (MOTHERSHIP_SEND_MESSAGE_EVENT) consumed in-place when Chat is already mounted, or a localStorage one-shot handoff (MothershipHandoffStorage) that survives navigation to the home surface.

  • browser-storage.ts: New MothershipHandoffStorage class with atomic clear-before-validate semantics, a 60-second max-age guard, and comprehensive unit tests including a regression for the previously-reported corrupted-entry bug.
  • events.ts: sendMothershipMessage gains an optional contexts argument, cancelable: true on the dispatched event, and a boolean return value so callers can detect whether a mounted consumer claimed the message.
  • log-details.tsx / home.tsx: The button and handleTroubleshoot callback build the logs context, attempt event delivery, fall back to store-and-navigate; the home surface consumes the handoff on mount (gated to !chatId to avoid claiming it on an existing chat route).

Confidence Score: 5/5

Safe to merge — the two-path delivery is correctly implemented, the atomic clear-before-validate pattern prevents stale entries, and all previously flagged issues have been addressed.

The handoff is one-shot by design: consume() clears unconditionally before any validity checks, so StrictMode double-mount and repeated sendMessage identity changes cannot replay the message. The store-then-navigate gate ensures no redirect occurs on a failed write. Existing callers of sendMothershipMessage are backward-compatible since the new contexts parameter is optional. Unit tests cover all edge cases introduced by this PR.

No files require special attention.

Important Files Changed

Filename Overview
apps/sim/lib/core/utils/browser-storage.ts Adds MothershipHandoffStorage with correct atomic clear-before-validate pattern; all edge cases (empty message, corrupted entry, expiry) are properly handled.
apps/sim/lib/core/utils/browser-storage.test.ts New unit tests cover round-trip, one-shot semantics, empty-message guard, corrupted-entry tombstone, and max-age expiry — comprehensive coverage of the new class.
apps/sim/lib/mothership/events.ts Adds optional contexts, cancelable event flag, and boolean return — backward-compatible with existing callers (terminal, console store) that ignore the return value.
apps/sim/app/workspace/[workspaceId]/home/home.tsx Handoff consumer useEffect correctly gated to !chatId and uses atomic consume(); event handler correctly claims with preventDefault() before forwarding contexts to sendMessage.
apps/sim/app/workspace/[workspaceId]/logs/components/log-details/log-details.tsx Adds canTroubleshoot guard and handleTroubleshoot callback with correct two-path delivery; navigation gated on successful store(); also refactors Version badge and Snapshot button to use EMCN components.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant User
    participant LogDetails as LogDetails (Logs route)
    participant Event as DOM CustomEvent
    participant Home as Home (Chat surface)
    participant Storage as MothershipHandoffStorage
    participant Router as Next.js Router

    User->>LogDetails: Click "Troubleshoot in Chat"
    LogDetails->>LogDetails: "Build ChatContext {kind:'logs', executionId}"
    LogDetails->>Event: sendMothershipMessage(message, [context]) cancelable:true

    alt Chat is already mounted (same-page)
        Event->>Home: MOTHERSHIP_SEND_MESSAGE_EVENT
        Home->>Event: e.preventDefault() — claims event
        Home->>Home: sendMessage(message, undefined, contexts)
        Event-->>LogDetails: returns true (consumed)
        LogDetails->>LogDetails: early return (no navigation)
    else Chat not mounted (cross-route)
        Event-->>LogDetails: returns false (no consumer)
        LogDetails->>Storage: "store({message, contexts, timestamp})"
        Storage-->>LogDetails: true (stored)
        LogDetails->>Router: push(/workspace/.../home)
        Router->>Home: mount (!chatId)
        Home->>Storage: consume()
        Storage->>Storage: clear() atomically
        Storage-->>Home: "{message, contexts}"
        Home->>Home: sendMessage(message, undefined, contexts)
    end
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant User
    participant LogDetails as LogDetails (Logs route)
    participant Event as DOM CustomEvent
    participant Home as Home (Chat surface)
    participant Storage as MothershipHandoffStorage
    participant Router as Next.js Router

    User->>LogDetails: Click "Troubleshoot in Chat"
    LogDetails->>LogDetails: "Build ChatContext {kind:'logs', executionId}"
    LogDetails->>Event: sendMothershipMessage(message, [context]) cancelable:true

    alt Chat is already mounted (same-page)
        Event->>Home: MOTHERSHIP_SEND_MESSAGE_EVENT
        Home->>Event: e.preventDefault() — claims event
        Home->>Home: sendMessage(message, undefined, contexts)
        Event-->>LogDetails: returns true (consumed)
        LogDetails->>LogDetails: early return (no navigation)
    else Chat not mounted (cross-route)
        Event-->>LogDetails: returns false (no consumer)
        LogDetails->>Storage: "store({message, contexts, timestamp})"
        Storage-->>LogDetails: true (stored)
        LogDetails->>Router: push(/workspace/.../home)
        Router->>Home: mount (!chatId)
        Home->>Storage: consume()
        Storage->>Storage: clear() atomically
        Storage-->>Home: "{message, contexts}"
        Home->>Home: sendMessage(message, undefined, contexts)
    end
Loading

Reviews (8): Last reviewed commit: "improvement(logs): use emcn Badge for th..." | Re-trigger Greptile

Comment thread apps/sim/lib/core/utils/browser-storage.ts
Comment thread apps/sim/app/workspace/[workspaceId]/logs/components/log-details/log-details.tsx Outdated
Review follow-ups:
- Same-route case (Cursor): LogDetailsContent is also embedded in the Chat
  resource panel, where router.push('/home') doesn't remount Home, so the
  mount-only handoff consume never fired. Generalize the existing
  sendMothershipMessage event to carry contexts and be cancelable: deliver
  straight to a mounted chat when one claims it, and only persist + navigate
  when none is listening.
- Corrupted-entry tombstone (Greptile): consume now clears whenever any entry
  exists, so a malformed/expired handoff can't linger across future mounts.
- Silent store failure (Greptile): only navigate when the handoff actually
  stored, so a failed write never strands the user on an empty chat.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 9a9a11a. Configure here.

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit a9b0812. Configure here.

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 4fad79e. Configure here.

Aligns the log-details panel's labeled action buttons (View Snapshot,
Troubleshoot in Chat) with the settings design language by swapping the
emcn Button for the canonical Chip pill. variant='primary' preserves the
prior filled emphasis; leftIcon keeps the icons canonical.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/app/workspace/[workspaceId]/home/home.tsx Outdated
Gate the mount-time handoff consume on `!chatId` so an existing
`/chat/[chatId]` mount can't claim a pending handoff if navigation races —
a handoff always targets a fresh chat.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

The detail-card rows all hovered to --surface-2, but the card itself is
--surface-2, so the hover was a no-op in light mode and only showed in dark.
It also implied clickability on static readout rows. Now only the clickable
Run ID row hovers, using the canonical --surface-active token; static rows
carry no hover.
Comment thread apps/sim/lib/core/utils/browser-storage.ts
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

1 issue from previous review remains unresolved.

Fix All in Cursor

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 398d954. Configure here.

Replaces the hand-rolled version span with the canonical Badge
(variant='green' size='md', pixel-identical tokens), so all three detail
badges (Level, Trigger, Version) render through the same component.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

1 issue from previous review remains unresolved.

Fix All in Cursor

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 462f4cd. Configure here.

@waleedlatif1 waleedlatif1 merged commit bca7f2c into staging Jul 2, 2026
12 checks passed
@waleedlatif1 waleedlatif1 deleted the worktree-logs-troubleshoot-in-chat branch July 2, 2026 00:19
waleedlatif1 added a commit that referenced this pull request Jul 2, 2026
Two concrete regressions from the earlier Chip conversion (#5341):
- Both chips used variant='primary' (the solid inverse-fill treatment),
  the heaviest chrome in the design system, reserved for a single standout
  action per context (Save, Upgrade, Add key) — never a peer among several
  row actions. Two solid pills stacked in a narrow side panel read as
  oversized. Switched both to the bare (default) chip, matching every
  analogous row action in Settings.
- The Version badge was size='md' while its siblings (Level, Trigger) are
  size='sm' — an inconsistency. Aligned to 'sm'.

Also folded the floating 'Troubleshoot in Chat' chip into the Details card
as its own row (matching 'Snapshot' exactly) instead of leaving it orphaned
below Workflow Output — every row in the card now shares one shape (label
left, trailing content right), consistent top to bottom.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant